var MODELO = {

    Tienda : function(nombreTienda) {
        this.nombreTienda = nombreTienda;
        this.clientes = new MODELO.Clientes();
        this.categoriasArticulos = new MODELO.Categorias();
        this.pedidos = new MODELO.Pedidos();
		
        //Observe que también podemos poner la adición de elementos en la propia tienda en vez de en las clases
        //Importante: No estoy retornando el objeto al que se añaden las categorías, sino el objeto que estoy añadiendo
        //ya que el que llama al método no tiene una referencia a él.
        this.addCategoria = function (id, nombre) {
            var categoria = new MODELO.Categoria(id, nombre);
            this.categoriasArticulos.addElemento(categoria);
            return categoria;
        }
    },

    Cliente : function(id, nombre) {
        //this.elemento = MODELO.Elemento;
        //this.elemento(id, nombre, MODELO.CLASES.Cliente, LITERALES.Cliente);
        //delete this.elemento;
        
        MODELO.Elemento.apply(this, [id, nombre, MODELO.CLASES.Cliente]);
		
		
    },

    Clientes : function() {
        MODELO.Lista.apply(this, [0, null, MODELO.CLASES.Clientes]);
        
		
        this.addCliente = function (cliente) {
            return this.addElemento(cliente);
        }

    },

    Categoria : function(id, nombre) {
        MODELO.Lista.apply(this,[id, nombre, MODELO.CLASES.Categoria]);
        
        this.addArticulo = function (id, nombre, precioArticulo) {
            return this.addElemento(new MODELO.Articulo(id, nombre, precioArticulo,this));
        }
    },

    Articulo : function(id, nombre, precioArticulo, categoria) {
        MODELO.Elemento.apply(this,[id, nombre, MODELO.CLASES.Articulo, categoria]);
        
        this.precioArticulo = precioArticulo;

    },

    Categorias : function() {
        MODELO.Lista.apply(this,[0, null, MODELO.CLASES.Categorias]);
        
		
        this.addCategoria = function (categoria) {
            return this.addElemento(categoria);
        }
                
        this.getArticulo = function(idArticulo) {
            return this.getElemento(idArticulo,MODELO.CLASES.Articulo,true);
        }
        
        this.getCategoria = function (idCategoria) {
            return this.getElemento(idCategoria);
        }
    },

    Pedido : function(idPedido, cliente, fechaPedido) {
        
        MODELO.Elemento.apply(this,[idPedido, idPedido, MODELO.CLASES.Pedido]);
        

        this.cliente = cliente;
        this.fechaPedido = fechaPedido;
        
        
        var lineas = new MODELO.Lista(0, null, MODELO.CLASES.LineasPedido);

        this.importePedido = function() {
            return lineas.elementos.reduce(function(suma, linea) {
                return suma + linea.importeLinea();
            }, 0);
        };
        
        this.vaciarCesta = function() {
            lineas = new MODELO.Lista(0, null, MODELO.CLASES.LineasPedido);
        }

        this.toString = function() {
            var s = MODELO.Elemento.prototype.toString.apply(this);            
            s += " Total " + this.importePedido().toFixed(2);
            s += "\n"+lineas.toString(); 
            return s;
        }

        this.getLineas = function() {
            return lineas;
        }

        this.addLinea = function(articulo, cantidadArticulo, precioVenta, orden) {
                        
            lineas.addElemento(new MODELO.LineaPedido(this,articulo, cantidadArticulo, precioVenta, orden));
        }
                
        this.getLinea = function (idArticulo) {            
            
            
            for (var i in lineas.elementos) {
                
                if (lineas.elementos[i].articulo.id == idArticulo) {
                    
                    return i; //Devuelvo el índice porque sino la funcione delete no borra;
                } 
            }
            
        }
                
        this.modificarPedido = function (idArticulo, cantidad) {
            var indice= this.getLinea(idArticulo);       
            
            if (indice) {                
                
                if (cantidad > 0) {
                    
                    lineas.elementos[indice].cantidadArticulo = cantidad;
                } else {
                    
                    lineas.elementos.splice(indice, 1) ;
                    
                }
            } else if (cantidad) {
                var articulo = tienda.categoriasArticulos.getArticulo(idArticulo); //Sería mejor que los objetos tuvieran una referencia tienda que crear un objeto global
                this.addLinea(articulo,cantidad);
            }
           
        }
        
        this.estaVacio = function () {
            return !lineas || lineas.tam() == 0;
        }
                

    },

    LineaPedido : function(pedido, articulo, cantidadArticulo, precioVenta, orden) {
        if (orden) {
            this.orden = orden;
        } else {
            this.orden = pedido.getLineas().tam() + 1;
        }

        MODELO.Elemento.apply(this,[this.orden, this.orden, MODELO.CLASES.LineaPedido, pedido]);
        

        this.articulo = articulo;
        this.cantidadArticulo = cantidadArticulo;
        if (precioVenta !== 0 && precioVenta) {
            this.precioVenta = precioVenta.toFixed(2);
        } else {
            this.precioVenta = this.articulo.precioArticulo;
        }
        this.importeLinea = function() {
            return this.cantidadArticulo * this.precioVenta;
        };
		
        this.toString = function() {
            var s = MODELO.Elemento.prototype.toString.apply(this);
            s += " Total " + this.importeLinea().toFixed(2);			 
            return s;
        }

    },

    Pedidos : function() {
        MODELO.Lista.apply(this,[0, 0, MODELO.CLASES.Pedidos]);        
    },

    CLASES : {
        Elemento : 'Elemento',
        Lista : 'Lista',
        Cliente : 'Cliente',
        Clientes : 'Clientes',
        Categoria : 'Categoria',
        Categorias : 'Categorias',
        Articulo : 'Articulo',
        Pedido : 'Pedido',
        Pedidos : 'Pedidos',
        LineaPedido : 'LineaPedido'
    },

    Elemento : function(id, valor, tipo, padre) {
        this.id = id;
        this.valor = valor;
        if (tipo) {
            this.tipo = tipo;
        } else {
            this.tipo = MODELO.CLASES.Elemento;
        }
        this.padre = padre;

        
        this.equals = function(elemento) {
            return (this.tipo == elemento.tipo && this.id == elemento.id);
        }
        
    },

    Lista : function(id, valor, tipo, padre) {
        if (tipo) {
            this.tipo = tipo;
        } else {
            this.tipo = MODELO.CLASES.Lista;
        }
		
        MODELO.Elemento.apply(this, [id, valor, tipo, padre]);
        this.esLista = true;
        

        this.elementos = [];

        this.tam = function() {
            return this.elementos.reduce(function(cuenta, valor) {
                return cuenta + 1;
            }, 0);
            
        //return this.elementos.length;¡CUIDADO, NO FUNCIONA TRAS UTILIZAR LA FUNCIÓN DELETE
        }
		
        this.addElemento = function(elemento) {
            this.elementos.push(elemento);
            return this;
        }

        this.getElemento = function(idElemento, tipo, busquedaIntrospectiva) {
            var i = 0;
            var elemento = null;

            for (i in this.elementos) {

                // alert("this.elementos[i]="+this.elementos[i].tipo +" "+
                // tipo);
                if (this.elementos[i].id == idElemento) {
                    // alert("aqui");
                    if (!tipo | (tipo && this.elementos[i].tipo == tipo)) {
                        // alert("aqui2 "+this.elementos[i]);
                        elemento = this.elementos[i];
                        break;
                    }
                }

                if (!elemento) {
                    if (busquedaIntrospectiva && this.elementos[i].esLista) {
                        elemento = this.elementos[i].getElemento(idElemento, tipo, false);
                        if (elemento) {
                            break;
                        }
                    }
                }

            }

            return elemento;
        }

        this.toString = function() {

            var s = "";
            if (this.valor) {
                s += this.valor;
            } else {
                s += this.tipo;
            }

            // s+= ":";

            this.elementos.forEach(function(elemento) {
                s += "\n\t" + elemento.toString();
            });
            return s;
        }
    }


};



var tienda = new MODELO.Tienda("PC DAW");

MODELO.Lista.prototype = new MODELO.Elemento();
MODELO.Cliente.prototype = new MODELO.Elemento();
MODELO.Clientes.prototype = new MODELO.Lista();
MODELO.Categoria.prototype = new MODELO.Lista();
MODELO.Articulo.prototype = new MODELO.Elemento();
MODELO.Categorias.prototype = new MODELO.Lista();

MODELO.Pedido.prototype = new MODELO.Elemento();

MODELO.LineaPedido.prototype = new MODELO.Elemento();
MODELO.Pedido.prototype = new MODELO.Lista();
//Lo ponemos aquí para poder llamarlo desde las clases hijas
MODELO.Elemento.prototype.toString = function() {
    var s = "";
    if (this.valor) {
        s += this.valor;
    } else {
        s += this.tipo;
    }
    for ( var atr in this) {
        if (this[atr] && this[atr].esLista && atr != "padre" ) {
            s += "\n" + this[atr].toString();//PELIGRO DE RECURSIÓN INFINITA. COMENTAR SI DA PROBLEMAS
        } else if (atr != "id" && atr != "tipo" && atr != "valor" && atr != "padre"  && typeof this[atr] != "function") {
            s += "\t" + atr + " " + this[atr];
					
        }
    }
    
    return s;
}